﻿using ArtMath.Core.Helper;
using ArtMath.Resource;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace ArtMath.Window
{
    public partial class InputFunctionWindow : Form
    {
        public static readonly Dictionary<string, string> MathFunctions = new Dictionary<string, string>();
        public static readonly HashSet<string> TrigonometricFunction = new HashSet<string>()
        {
            "sin","cos","tan","tg","sinh","cosh","tanh","cot","ctg","sec","csc","arcsin", "arccos","arctan",
            "arccot","arcctg","arcsec","arccsc"
        };
        //List<clsFormulaBase> formulas = new List<clsFormulaBase>();
        //frmIntellisense sense;
        public static bool ContainsTrigonometricFunction(string exp)
        {
            foreach (string item in TrigonometricFunction)
            {
                bool contain = false;
                Utility.ForEachSubString(exp, item, (int index) =>
                {
                    if ((index == 0 || !char.IsLetter(exp[index - 1])) && (index + item.Length >= exp.Length || !char.IsLetter(exp[index + item.Length])))
                    {
                        contain = true;
                    }
                    return !contain;
                });
                if (contain) return true;
            }
            return false;
        }
        public static void LocalizeFunctionName()
        {
            MathFunctions.Clear();
            MathFunctions.Add("sin", Resources.Translate("Sine"));
            MathFunctions.Add("cos", Resources.Translate("Cosine"));
            MathFunctions.Add("tan/tg", Resources.Translate("Tangent"));
            MathFunctions.Add("sinh", Resources.Translate("HyperbolicSine"));
            MathFunctions.Add("cosh", Resources.Translate("HyperbolicCosine"));
            MathFunctions.Add("tanh", Resources.Translate("HyperbolicTangent"));
            MathFunctions.Add("cot/ctg", Resources.Translate("Cotangent"));
            MathFunctions.Add("sec", Resources.Translate("Secant"));
            MathFunctions.Add("csc", Resources.Translate("Cosecant"));
            MathFunctions.Add("arcsin", Resources.Translate("Arcsine"));
            MathFunctions.Add("arccos", Resources.Translate("Arccosine"));
            MathFunctions.Add("arctan", Resources.Translate("Arctangent"));
            MathFunctions.Add("arccot/arcctg", Resources.Translate("Arccotangent"));
            MathFunctions.Add("arcsec", Resources.Translate("Arcsecant"));
            MathFunctions.Add("arccsc", Resources.Translate("Arccosecant"));
            MathFunctions.Add("abs", Resources.Translate("Absolute"));
            MathFunctions.Add("sgn", Resources.Translate("Sign"));
            MathFunctions.Add("ceil", Resources.Translate("Ceil"));
            MathFunctions.Add("floor", Resources.Translate("Floor"));
            MathFunctions.Add("rnd", Resources.Translate("Round"));
            MathFunctions.Add("max", Resources.Translate("Maximum"));
            MathFunctions.Add("min", Resources.Translate("Minimum"));
        }
        public InputFunctionWindow()
        {
            InitializeComponent();
            foreach (KeyValuePair<string, string> item in MathFunctions)
            {
                lvFunction.Items.Add($"{item.Value}({item.Key})");
            }
            if (Program.WinDocuments.LinkedDocument.SelectedPad.CoordinateType == CoordinateSystemType.RectangularCoordinate)
            {
                cbIndependentVariable.Items.Add("x");
                cbIndependentVariable.Items.Add("y");
                cbIndependentVariable.SelectedIndex = 0;
            }
            else
            {
                cbIndependentVariable.Items.Add("ρ");
                cbIndependentVariable.Items.Add("θ");
                cbIndependentVariable.SelectedIndex = 1;
            }
            Button[] btns = new Button[] { zero, one, two, three, four, five, six, seven, eight, nine, btnPoint, xy, plus, minus, multiplication, divide, btnPow, left_bracket, right_bracket, pi, e };
            for (int i = 0; i < btns.Length; i++)
            {
                btns[i].Click += (object sender, EventArgs e) =>
                {
                    insertText(sender == multiplication ? "*" : sender == divide ? "/" : (sender as ButtonBase).Text);
                };
            }
            linearF.Dock = DockStyle.Top;
            linearF.Height = plFriend.Height;
            label13_Click(label13, EventArgs.Empty);
        }
        [Browsable(false)]
        public string FunctionExpression
        {
            get { return linearF.Text; }
        }
        [Browsable(false)]
        public string FunctionName
        {
            get { return tbFunctionName.Text; }
        }
        [Browsable(false)]
        public string IndependentVariable
        {
            get { return cbIndependentVariable.SelectedItem.ToString(); }
        }
        void insertText(string text, int offset = 1)
        {
            int ss = linearF.SelectionStart;
            linearF.Text = linearF.Text.Substring(0, ss) + text + linearF.Text.Substring(ss + linearF.SelectionLength, linearF.TextLength - ss - linearF.SelectionLength);
            linearF.SelectionStart = ss + offset;
            linearF.Focus();
        }
        private void label12_Click(object sender, EventArgs e)
        {
            label12.BackColor = Color.DeepSkyBlue;
            label12.ForeColor = Color.White;
            label13.BackColor = Color.Transparent;
            label13.ForeColor = Color.OrangeRed;
            plFriend.Visible = true;
            linearF.Visible = false;
        }
        private void label13_Click(object sender, EventArgs e)
        {
            label12.BackColor = Color.Transparent;
            label12.ForeColor = Color.DeepSkyBlue;
            label13.BackColor = Color.OrangeRed;
            label13.ForeColor = Color.White;
            plFriend.Visible = false;
            linearF.Visible = true;
        }
        //private void pbFormula_MouseDown(object sender, MouseEventArgs e)
        //{
        //    foreach (clsFormulaBase item in formulas)
        //    {
        //        if (e.X >= item.Location.X && e.X <= item.Right && e.Y >= item.Location.Y && e.Y <= item.Bottom)
        //        {
        //            item.Edit = true;
        //            break;
        //        }
        //    }
        //}
        //private void pbFormula_Paint(object sender, PaintEventArgs e)
        //{
        //    Graphics gra = e.Graphics;
        //    gra.SmoothingMode = SmoothingMode.HighQuality;
        //    foreach (clsFormulaBase item in formulas)
        //    {
        //        item.Paint(gra);
        //    }
        //}
        private void fs_Click(object sender, EventArgs e)
        {
            insertText("()/()");
        }
        private void sqrt_Click(object sender, EventArgs e)
        {
            insertText("sqrt()", 5);
        }
        private void cubeRoot_Click(object sender, EventArgs e)
        {
            insertText("cbrt()", 5);
        }
        private void anyRoot_Click(object sender, EventArgs e)
        {
            insertText("rt(,)", 3);
        }
        private void square_Click(object sender, EventArgs e)
        {
            insertText("()^2", 1);
        }
        private void cube_Click(object sender, EventArgs e)
        {
            insertText("()^3", 1);
        }
        private void mz_Click(object sender, EventArgs e)
        {
            insertText("()^()", 1);
        }
        private void ln_Click(object sender, EventArgs e)
        {
            insertText("ln()", 3);
        }
        private void lg_Click(object sender, EventArgs e)
        {
            insertText("lg()", 3);
        }
        private void log_Click(object sender, EventArgs e)
        {
            insertText("log(,)", 4);
        }
        private void backSpace_Click(object sender, EventArgs e)
        {
            int ss = linearF.SelectionStart;
            if (linearF.SelectionLength == 0)
            {
                if (ss > 0)
                {
                    linearF.Text = linearF.Text.Substring(0, ss - 1) + linearF.Text.Substring(ss, linearF.TextLength - ss);
                    linearF.SelectionStart = ss - 1;
                }
            }
            else
            {
                linearF.Text = linearF.Text.Substring(0, ss) + linearF.Text.Substring(ss + linearF.SelectionLength, linearF.TextLength - ss - linearF.SelectionLength);
                linearF.SelectionStart = ss;
            }
            linearF.Focus();
        }
        private void lvFunction_ItemActivate(object sender, EventArgs e)
        {
            string[] tokens = lvFunction.SelectedItems[0].Text.Split('(');
            tokens = tokens[1].Substring(0, tokens[1].Length - 1).Split('/');
            tokens[0] += "(" + (lvFunction.SelectedIndices[0] > 18 ? "," : string.Empty) + ")";
            insertText(tokens[0], tokens[0].Length - (lvFunction.SelectedIndices[0] > 18 ? 2 : 1));
        }
        private void pbSaveFormula_Click(object sender, EventArgs e)
        {
            //clsFormulaBase fb = new clsGS(pbFormula, new clsNormal(pbFormula, "x"), new clsNormal(pbFormula, "x"));
            //formulas.Add(fb);
            //fb.Location = new PointD(10, 10);
        }
        private void cbIndependentVariable_SelectedIndexChanged(object sender, EventArgs e)
        {
            xy.Text = IndependentVariable;
        }

        private void linearF_TextChanged(object sender, EventArgs e)
        {
            btnOK.Enabled = linearF.TextLength > 0;
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            DialogResult = DialogResult.OK;
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            DialogResult = DialogResult.Cancel;
        }
    }
}
